package com.york.tinyrpc.protoss.proxy;

import com.github.javafaker.Faker;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.*;
import java.time.LocalDate;
import java.util.*;

/**
 * 基于JDK的动态代理实现
 * 实现Mock服务，同TinyRpc服务类似，只是不需要远程调用，而是通过RPC的返回类型返回一个默认的对象实现Mock功能
 */
public class MockServiceHandler implements InvocationHandler {

    private static final Logger log = LoggerFactory.getLogger(MockServiceHandler.class);

    /**
     * 添加Faker实例（线程安全）
     */
    private static final Faker faker = new Faker();

    /**
     * 缓存常见类型生成器（扩展用）
     */
    private static final Map<Class<?>, MockValueGenerator> generators = new HashMap<>();

    /**
     * 静态代码初始化
     */
    static {
        // 初始化基础类型生成器
        generators.put(String.class, () -> faker.lorem().word());
        generators.put(Integer.class, faker.number()::randomDigit);
        generators.put(Long.class, faker.number()::randomNumber);
        // Double类型的mock需要设定最大最小值以及小数点位数的指定
        generators.put(Double.class, () ->
                faker.number().randomDouble(2, 0, 1000));
        generators.put(Boolean.class, faker.bool()::bool);
        generators.put(Date.class, () -> faker.date().birthday());
        generators.put(LocalDate.class, () -> LocalDate.now().minusDays(faker.number().numberBetween(1, 365)));
        generators.put(List.class, () -> Collections.singletonList(faker.lorem().word()));
        generators.put(Map.class, () -> Collections.singletonMap(faker.lorem().word(), faker.lorem().word()));
    }

    /**
     * Mock调用代理
     *
     * @param proxy  代理对象
     * @param method 被代理对象的方法
     * @param args   被代理对象方法的参数
     * @return Object 代理对象运行结果
     * @throws Throwable
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

        // 得到返回类型
        Class<?> returnType = method.getReturnType();
        log.info("MockServiceHandler invoke method:{}, returnType:{}", method.getName(), returnType);
        return generateMockValue(returnType);
    }

    /**
     * 返回Mock对象，根据返回类型得到默认对象即可
     *
     * @param type
     * @return
     */
    private Object generateMockValue(Class<?> type) {
        // 处理Void类型
        if (type == void.class || type == Void.class) {
            return null;
        }

        // 优先处理基本类型
        if (type.isPrimitive()) {
            return handlePrimitiveType(type);
        }

        // 检查预定义生成器
        MockValueGenerator generator = generators.get(type);
        if (generator != null) {
            return generator.generate();
        }

        // 处理数组类型
        if (type.isArray()) {
            return handleArrayType(type);
        }

        // 处理枚举类型
        if (type.isEnum()) {
            return handleEnumType(type);
        }

        // 处理自定义对象（递归生成字段）
        return handleCustomType(type);
    }

    /**
     * 处理基本数据类型
     *
     * @param type
     * @return
     */
    private Object handlePrimitiveType(Class<?> type) {
        if (boolean.class == type) return false;
        if (byte.class == type) return (byte) 0;
        if (char.class == type) return '\u0000';
        if (short.class == type) return (short) 0;
        if (int.class == type) return 0;
        if (long.class == type) return 0L;
        if (float.class == type) return 0.0f;
        if (double.class == type) return 0.0d;
        return null;
    }

    /**
     * 处理数组类型
     *
     * @param arrayType
     * @return
     */
    private Object handleArrayType(Class<?> arrayType) {
        Class<?> componentType = arrayType.getComponentType();
        int length = faker.number().numberBetween(1, 5);
        Object array = Array.newInstance(componentType, length);
        for (int i = 0; i < length; i++) {
            Array.set(array, i, generateMockValue(componentType));
        }
        return array;
    }

    /**
     * 处理枚举类型
     *
     * @param enumType
     * @return
     */
    private Object handleEnumType(Class<?> enumType) {
        Object[] enumConstants = enumType.getEnumConstants();
        return enumConstants.length > 0 ?
                enumConstants[faker.random().nextInt(enumConstants.length)] : null;
    }

    /**
     * 处理自定义类型
     *
     * @param type
     * @return
     */
    private Object handleCustomType(Class<?> type) {
        try {
            // 尝试通过无参构造器创建实例
            Constructor<?> constructor = type.getDeclaredConstructor();
            constructor.setAccessible(true);
            Object instance = constructor.newInstance();

            // 递归填充字段值（基础实现）
            Arrays.stream(type.getDeclaredFields())
                    .filter(f -> !Modifier.isFinal(f.getModifiers()))
                    .forEach(field -> {
                        try {
                            field.setAccessible(true);
                            field.set(instance, generateMockValue(field.getType()));
                        } catch (Exception e) {
                            log.warn("字段:{} 设置失败!: {}", field.getName(), e.getMessage());
                        }
                    });
            return instance;
        } catch (Exception e) {
            log.warn("创建Mock实例: {} 失败: {}", type.getSimpleName(), e.getMessage());
            return null;
        }
    }

    @FunctionalInterface
    private interface MockValueGenerator {
        Object generate();
    }
}